package com.sjft.cloud.extension.generate;

import com.sjft.cloud.extension.generate.constant.CustomConstVal;
import com.sjft.cloud.extension.generate.config.CustomGlobalConfig;
import com.sjft.cloud.extension.generate.config.CustomPackageConfig;
import com.sjft.cloud.extension.generate.bean.CustomTableInfo;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.ConstVal;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.builder.ConfigBuilder;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import org.springframework.beans.BeanUtils;

import java.io.File;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * Generator
 *
 * @author Jin
 */
public class Generator extends AutoGenerator {

    public CustomTableInfo convertCustomTableInfo(TableInfo tableInfo) {
        CustomTableInfo customTableInfo = new CustomTableInfo();
        BeanUtils.copyProperties(tableInfo, customTableInfo);
        //设置inputDTO文件名
        customTableInfo.setInputDtoName(String.format(CustomConstVal.INPUT_DTO, tableInfo.getEntityName()));
        //设置updateDTO文件名
        customTableInfo.setUpdateDtoName(String.format(CustomConstVal.UPDATE_DTO, tableInfo.getEntityName()));
        //设置queryDTO文件名
        customTableInfo.setQueryDtoName(String.format(CustomConstVal.QUERY_DTO, tableInfo.getEntityName()));
        //设置VO文件名
        customTableInfo.setEntityVoName(tableInfo.getEntityName() + CustomConstVal.VO);
        //设置Wrapper文件名
        customTableInfo.setWrapperName(tableInfo.getEntityName() + CustomConstVal.WRAPPER);
        //设置Entity文件名为DO
        customTableInfo.setEntityName(tableInfo.getEntityName() + CustomConstVal.DO);
        //FEIGN
        customTableInfo.setFeignName(String.format(CustomConstVal.FEIGN, tableInfo.getEntityName()));
        //FEIGN_FALLBACK
        customTableInfo.setFeignFallBackName(String.format(CustomConstVal.FEIGN_FALLBACK, tableInfo.getEntityName()));
        return customTableInfo;
    }

    @Override
    protected ConfigBuilder pretreatmentConfigBuilder(ConfigBuilder config) {
        ConfigBuilder configBuilder = super.pretreatmentConfigBuilder(config);
        PackageConfig packageConfig = this.getPackageInfo();
        Map<String, String> packageInfo = config.getPackageInfo();
        Map<String, String> pathInfo = config.getPathInfo();
        List<TableInfo> tableInfoList = config.getTableInfoList();
        CustomGlobalConfig globalConfig = (CustomGlobalConfig) this.getGlobalConfig();
        //增加自定义属性
        config.setTableInfoList(tableInfoList.stream().map(this::convertCustomTableInfo).collect(Collectors.toList()));

        //DTO
        String inputDTO = String.format(CustomConstVal.INPUT_DTO, "");
        String updateDTO = String.format(CustomConstVal.UPDATE_DTO, "");
        String queryDTO = String.format(CustomConstVal.QUERY_DTO, "");
        String feign = String.format(CustomConstVal.FEIGN, "");
        String feignFallback = String.format(CustomConstVal.FEIGN_FALLBACK, "");

        CustomPackageConfig customPackageConfig = (CustomPackageConfig) packageConfig;

        //============================[ 接口包名 package 重写]==============================

        //inputDTO包设置
        packageInfo.put(inputDTO, joinPackage(packageConfig.getParent() + StringPool.DOT + customPackageConfig.getApi(), customPackageConfig.getDto()));

        //updateDTO包设置
        packageInfo.put(updateDTO, joinPackage(packageConfig.getParent() + StringPool.DOT + customPackageConfig.getApi(), customPackageConfig.getDto()));

        //queryDTO包设置
        packageInfo.put(queryDTO, joinPackage(packageConfig.getParent() + StringPool.DOT + customPackageConfig.getApi(), customPackageConfig.getDto()));

        //Entity包设置
        packageInfo.put(ConstVal.ENTITY, joinPackage(packageConfig.getParent() + StringPool.DOT + customPackageConfig.getApi(), "domain"));

        //VO包设置
        packageInfo.put(CustomConstVal.VO, joinPackage(packageConfig.getParent() + StringPool.DOT + customPackageConfig.getApi(), customPackageConfig.getVo()));

        //FEIGN包设置
        packageInfo.put(feign, joinPackage(packageConfig.getParent() + StringPool.DOT + customPackageConfig.getApi(), customPackageConfig.getFeign()));

        //FEIGN_FALLBACK包设置
        packageInfo.put(feignFallback, joinPackage(packageConfig.getParent() + StringPool.DOT + customPackageConfig.getApi(), customPackageConfig.getFallback()));


        //==============================[ 服务包名 package 重写]============================

        //Wrapper包设置
        packageInfo.put(CustomConstVal.WRAPPER, joinPackage(packageConfig.getParent() + StringPool.DOT + customPackageConfig.getApp(), customPackageConfig.getWrapper()));

        //Controller包设置
        packageInfo.put(ConstVal.CONTROLLER, joinPackage(packageConfig.getParent() + StringPool.DOT + customPackageConfig.getApp(), packageConfig.getController()));

        //Service包设置
        packageInfo.put(ConstVal.SERVICE, joinPackage(packageConfig.getParent() + StringPool.DOT + customPackageConfig.getApp(), packageConfig.getService()));

        //ServiceImpl包设置
        packageInfo.put(ConstVal.SERVICE_IMPL, joinPackage(packageConfig.getParent() + StringPool.DOT + customPackageConfig.getApp(), packageConfig.getServiceImpl()));

        //XML包设置
        packageInfo.put(ConstVal.XML, joinPackage(packageConfig.getParent() + StringPool.DOT + customPackageConfig.getApp(), packageConfig.getXml()));

        //MAPPER包设置
        packageInfo.put(ConstVal.MAPPER, joinPackage(packageConfig.getParent() + StringPool.DOT + customPackageConfig.getApp(), packageConfig.getMapper()));

        //=================================[ TemplatePath 重写]=================================

        //Wrapper 路径
        setPathInfo(pathInfo, CustomConstVal.TEMPLATE_WRAPPER, globalConfig.getAppFileOutputDir(), CustomConstVal.WRAPPER_PATH, CustomConstVal.WRAPPER);

        //Service 路径
        setPathInfo(pathInfo, CustomConstVal.TEMPLATE_SERVICE, globalConfig.getAppFileOutputDir(), CustomConstVal.SERVICE_PATH, CustomConstVal.SERVICE);

        //ServiceImpl 路径
        setPathInfo(pathInfo, CustomConstVal.TEMPLATE_SERVICE_IMPL, globalConfig.getAppFileOutputDir(), CustomConstVal.SERVICE_IMPL_PATH, CustomConstVal.SERVICE_IMPL);

        //Mapper 路径
        pathInfo.put(ConstVal.MAPPER_PATH, joinPath(globalConfig.getAppFileOutputDir(), packageInfo.get(ConstVal.MAPPER)));

        //Controller 路径
        pathInfo.put(ConstVal.CONTROLLER_PATH, joinPath(globalConfig.getAppFileOutputDir(), packageInfo.get(ConstVal.CONTROLLER)));

        //MapperXml 路径
        pathInfo.put(ConstVal.XML_PATH, joinPath(globalConfig.getAppFileOutputDir(), packageInfo.get(ConstVal.XML)));

        //000------=======----08888%%%%

        //Feign 路径
        setPathInfo(pathInfo, CustomConstVal.TEMPLATE_FEIGN, globalConfig.getApiFileOutputDir(), CustomConstVal.FEIGN_PATH, feign);

        //FeignFallback 路径
        setPathInfo(pathInfo, CustomConstVal.TEMPLATE_FEIGN_FALLBACK, globalConfig.getApiFileOutputDir(), CustomConstVal.FEIGN_FALLBACK_PATH, feignFallback);


        //Entity 路径
        pathInfo.put(ConstVal.ENTITY_PATH, joinPath(globalConfig.getApiFileOutputDir(), packageInfo.get(ConstVal.ENTITY)));

        //inputDTO 路径
        setPathInfo(pathInfo, CustomConstVal.TEMPLATE_INPUT_DTO, globalConfig.getApiFileOutputDir(), CustomConstVal.DTO_PATH, inputDTO);

        //queryDTO 路径
        setPathInfo(pathInfo, CustomConstVal.TEMPLATE_QUERY_DTO, globalConfig.getApiFileOutputDir(), CustomConstVal.DTO_PATH, updateDTO);

        //updateDTO 路径
        setPathInfo(pathInfo, CustomConstVal.TEMPLATE_UPDATE_DTO, globalConfig.getApiFileOutputDir(), CustomConstVal.DTO_PATH, queryDTO);

        //VO 路径
        setPathInfo(pathInfo, CustomConstVal.TEMPLATE_VO, globalConfig.getApiFileOutputDir(), CustomConstVal.VO_PATH, CustomConstVal.VO);

        return configBuilder;
    }


    private String joinPackage(String parent, String subPackage) {
        if (StringUtils.isBlank(parent)) {
            return subPackage;
        }
        return parent + StringPool.DOT + subPackage;
    }

    private void setPathInfo(Map<String, String> pathInfo, String template, String outputDir, String path, String module) {
        if (StringUtils.isNotBlank(template)) {
            Map<String, String> packageInfo = getConfig().getPackageInfo();
            pathInfo.put(path, joinPath(outputDir, packageInfo.get(module)));
        }
    }

    private String joinPath(String parentDir, String packageName) {
        if (!StringUtils.endsWith(parentDir, File.separator)) {
            parentDir += File.separator;
        }
        packageName = packageName.replaceAll("\\.", StringPool.BACK_SLASH + File.separator);
        return parentDir + packageName;
    }
}

